﻿using System;
using System.Collections.Generic;

namespace ApiScanner.Core
{
    public sealed class TestRunner
    {
        private readonly ScannerConfigurationSection _Configuration;
        private static readonly Dictionary<Type, Func<IScanner>> _ScannerFactory = new Dictionary<Type, Func<IScanner>>
                                                                              {
                                                                                  {typeof(ExchangeStoreScannerTestConfigurationElement), () => new ExchangeStoreScanner()},
                                                                                  {typeof(FileSystemScannerTestConfigurationElement), () => new FileSystemScanner() },
                                                                                  {typeof(SmtpServerEventScannerTestConfigurationElement), () => new SmtpServerEventScanner()}
                                                                              };
        public TestRunner(ScannerConfigurationSection configuration)
        {
            if (configuration == null) throw new ArgumentNullException("configuration");
            _Configuration = configuration;
        }

        public IEnumerable<Artifact> Run(Action<string> progressHandler)
        {
            try
            {
                progressHandler("Scanning for event bindings...");
                foreach (TestConfigurationElement testConfiguration in _Configuration.Tests)
                {
                    var factory = _ScannerFactory[testConfiguration.GetType()];
                    var scanner = factory();
                    ScannerError error = null;
                    try
                    {
                        scanner.Initialize(testConfiguration);
                    }
                    catch (Exception ex)
                    {
                        error = new ScannerError(string.Format("Initialization of test {0}", testConfiguration.ConfigurationElementName), ex);
                    }
                    if (error != null)
                    {
                        yield return error;
                        continue;
                    }

                    foreach (var artifact in scanner.EnumerateArtifacts(progressHandler))
                    {
                        yield return artifact;
                    }
                }
            }
            finally
            {
                progressHandler("Scan complete.");
            }
        }
    }
}